#!/usr/bin/env python
# -*- coding: utf-8 -*-

import mmap
import struct

class basic_number_types:	
	"""Basic number types"""
	
	def dateTimeNumber(self,bytes):
		"""
		Input is a 12-byte value representation of the time and date. 
		It returns a list (Y,m,d,H,i,s).
		"""
		return struct.unpack('>hhhhhh',bytes)
	
	def response16Number(self,bytes):
		"""
		Input is a 8-byte value, used to associate a normalized device code with a measurement value.
		Returns list (uInt16Number,reserved zero, measurement value)
		"""
		return struct.unpack('>hhi',bytes)
	
	def s15Fixed16Number(self, bytes):
		"""Input is 4-byte quantity"""
		return struct.unpack('>i',bytes)[0] / 65536.0

	def u16Fixed16Number(self, bytes):
		"""Input is 4-byte quantity"""
		return struct.unpack('>I',bytes)[0] / 65536.0
	
	def u1Fixed15Number(self, bytes):
		return struct.unpack('>H',bytes)[0] / 32768.0
		
	def u8Fixed8Number(self, bytes):
		return struct.unpack('>h',bytes)[0] / 256.0

	def uInt16Number(self, bytes):
		return struct.unpack('>H',bytes)[0]
	
	def uInt32Number(self, bytes):
		return struct.unpack('>I',bytes)[0]
	
	def uInt64Number(self, bytes):
		return struct.unpack('>L',bytes)[0]
	
	def uInt8Number(self, bytes):
		return struct.unpack('>B',bytes)[0]
	
	def XYZNumber(self, xyz_bytes):			
		X = self.s15Fixed16Number(xyz_bytes[0:4])
		Y = self.s15Fixed16Number(xyz_bytes[4:8])
		Z = self.s15Fixed16Number(xyz_bytes[8:12])
		
		return X,Y,Z
	
	#
	# For CIE Lab format
	#
	
	def cie_l(self,bytes):
		if len(bytes) == 2:
			return struct.unpack('>H',bytes)[0] / 65535.0 * 100
		else:
			return struct.unpack('>B',bytes)[0] / 255.0 * 100
	
	def cie_ab(self,bytes,bit=8):
		return struct.unpack('>B',bytes)[0] - 128.0


class icc(basic_number_types):
	"""
	If you have custom file open function/class assign the opened file
	to icc.data variable.
	
	You can also open profile with a build in class 'open_file(icc_file)'
	and it automatically assigns the file to icc.data
	self.data = open(icc_file,'r+b')
	"""
	data = None
	
	####################################################################
	#
	# ICC Tags, Hex codes, Signatures
	#
	####################################################################
	
	# Required ICC tags
	# -----------------------------
	# 
	# With the exception of DeviceLink profiles, all profiles shall 
	# contain the following tags: profileDescriptionTag, copyrightTag, 
	# mediaWhitePointTag, chromaticAdaptationTag
	#

	input_tags = (	'profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'AToB0Tag',
					'AToB1Tag',
					'AToB2Tag',
					'BToA0Tag',
					'BToA1Tag',
					'BToA2Tag',
					'redMatrixColumnTag',
					'greenMatrixColumnTag',
					'blueMatrixColumnTag',
					'redTRCTag',
					'greenTRCTag',
					'blueTRCTag',
					'gamutTag',
					'grayTRCTag'
					)
	
	display_tags = ('profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'AToB0Tag',
					'AToB1Tag',
					'AToB2Tag',
					'BToA0Tag',
					'BToA1Tag',
					'BToA2Tag',
					'redMatrixColumnTag',
					'greenMatrixColumnTag',
					'blueMatrixColumnTag',
					'redTRCTag',
					'greenTRCTag',
					'blueTRCTag',
					'gamutTag',
					'grayTRCTag'
					)
	
	output_tags = (	'profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'AToB0Tag',
					'AToB1Tag',
					'AToB2Tag',
					'BToA0Tag',
					'BToA1Tag',
					'BToA2Tag',
					'gamutTag',
					'colorantTableTag',
					'grayTRCTag'
					)
	
	link_tags = (	'profileDescriptionTag',
					'copyrightTag',
					'profileSequenceDescTag',
					'AToB0Tag',
					'colorantTableTag',
					'colorantTableOutTag'
					)

	cs_conv_tags = ('profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'AToB0Tag',
					'AToB1Tag',
					'AToB2Tag',
					'BToA0Tag',
					'BToA1Tag',
					'BToA2Tag',
					'gamutTag'
					)
					
	abstract_tags = ('profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'AToB0Tag'
					)
	
	named_colour_tags = ('profileDescriptionTag',
					'copyrightTag',
					'mediaWhitePointTag',
					'chromaticAdaptationTag',
					'namedColor2Tag'
					)
	
	public_tags = {}
	
	public_tags['A2B0'] = 'AToB0Tag' # type lut8Type or lut16Type or lutAtoBType
	public_tags['A2B1'] = 'AToB1Tag' # type lut8Type or lut16Type or lutAtoBType
	public_tags['A2B2'] = 'AToB2Tag' # type lut8Type or lut16Type or lutAtoBType
	public_tags['B2A0'] = 'BToA0Tag' # type lut8Type or lut16Type or lutBtoAType
	public_tags['B2A1'] = 'BToA1Tag' # type lut8Type or lut16Type or lutBtoAType
	public_tags['B2A2'] = 'BToA2Tag' # type lut8Type or lut16Type or lutBtoAType
	
	public_tags['rXYZ'] = 'redMatrixColumnTag' 		# type XYZType
	public_tags['gXYZ'] = 'greenMatrixColumnTag' 	# type XYZType
	public_tags['bXYZ'] = 'blueMatrixColumnTag' 	# type XYZType
	
	public_tags['calt'] = 'calibrationDateTimeTag' 	# dateTimeType
	public_tags['targ'] = 'charTargetTag' 			# textType
	public_tags['chad'] = 'chromaticAdaptationTag' 	# s15Fixed16ArrayType
	public_tags['chrm'] = 'chromaticityTag' 		# chromaticity type
	public_tags['clro'] = 'colorantOrderTag' 		# colorantOrderType
	public_tags['clrt'] = 'colorantTableTag' 		# colorantTableType
	public_tags['clot'] = 'colorantTableOutTag' 	# colorantTableType
	public_tags['cprt'] = 'copyrightTag' 			# multiLocalizedUnicodeType
	public_tags['dmnd'] = 'deviceMfgDescTag' 		# multiLocalizedUnicodeType
	public_tags['dmdd'] = 'deviceModelDescTag' 		# multiLocalizedUnicodeType
	public_tags['gamt'] = 'gamutTag' # lut8Type or lut16Type or lutBtoAType
	
	public_tags['kTRC'] = 'grayTRCTag' 	# curveType or parametricCurveType
	public_tags['rTRC'] = 'redTRCTag' 	# curveType or parametricCurveType
	public_tags['gTRC'] = 'greenTRCTag' # curveType or parametricCurveType
	public_tags['bTRC'] = 'blueTRCTag' 	# curveType or parametricCurveType
	
	public_tags['lumi'] = 'luminanceTag' 		# XYZType
	public_tags['meas'] = 'measurementTag' 		# measurementType
	public_tags['bkpt'] = 'mediaBlackPointTag' 	# XYZType
	public_tags['wtpt'] = 'mediaWhitePointTag' 	# XYZType
	public_tags['ncl2'] = 'namedColor2Tag' 		# namedColor2Type
	public_tags['resp'] = 'outputResponseTag' 	# responseCurveSet16Type
	
	public_tags['pre0'] = 'preview0Tag'	# lut8Type or lut16Type or lutBtoAType
	public_tags['pre1'] = 'preview1Tag' # lut8Type or lut16Type or lutBtoAType
	public_tags['pre2'] = 'preview2Tag' # lut8Type or lut16Type or lutBtoAType
	
	public_tags['desc'] = 'profileDescriptionTag' 	# multiLocalizedUnicodeType
	public_tags['pseq'] = 'profileSequenceDescTag' 	# profileSequenceDescType	
	public_tags['tech'] = 'technologyTag' 			# signatureType
	public_tags['vued'] = 'viewingCondDescTag' 		# multiLocalizedUnicodeType
	public_tags['view'] = 'viewingConditionsTag'	# viewingConditionsType
	
	# Technology signatures
	# -----------------------------
	techs = {}
	techs['fscn'] = 'Film Scanner' 					# 6673636Eh
	techs['dcam'] = 'Digital Camera' 				# 6463616Dh
	techs['rscn'] = 'Reflective Scanner' 			# 7273636Eh
	techs['ijet'] = 'Ink Jet Printer' 				# 696A6574h
	techs['twax'] = 'Thermal Wax Printer' 			# 74776178h
	techs['epho'] = 'Electrophotographic Printer' 	# 6570686Fh
	techs['esta'] = 'Electrostatic Printer' 		# 65737461h
	techs['dsub'] = 'Dye Sublimation Printer' 		# 64737562h
	techs['rpho'] = 'Photographic Paper Printer' 	# 7270686Fh
	techs['fprn'] = 'Film Writer' 					# 6670726Eh
	techs['vidm'] = 'Video Monitor' 				# 7669646Dh
	techs['vidc'] = 'Video Camera' 					# 76696463h
	techs['pjtv'] = 'Projection Television' 		# 706A7476h
	techs['CRT '] = 'Cathode Ray Tube Display' 		# 43525420h
	techs['PMD '] = 'Passive Matrix Display' 		# 504D4420h
	techs['AMD '] = 'Active Matrix Display' 		# 414D4420h
	techs['KPCD'] = 'Photo CD' 						# 4B504344h
	techs['imgs'] = 'PhotoImageSetter' 				# 696D6773h
	techs['grav'] = 'Gravure' 						# 67726176h
	techs['offs'] = 'Offset Lithography' 			# 6F666673h
	techs['silk'] = 'Silkscreen' 					# 73696C6Bh
	techs['flex'] = 'Flexography' 					# 666C6578h
	
	# Profil/Device Class signature
	# -----------------------------
	
	profiles = {}
	profiles['\x73\x63\x6E\x72'] = 'scnr' #'input_device' # 'scnr'
	profiles['\x6D\x6E\x74\x72'] = 'mntr' #'display_device' # 'mntr'
	profiles['\x70\x72\x74\x72'] = 'prtr' #'output_device' # 'prtr'
	profiles['\x6C\x69\x6E\x6B'] = 'link' #'device_link' # 'link'
	profiles['\x73\x70\x61\x63'] = 'spac' #'color_space_conversion' # 'spac'
	profiles['\x61\x62\x73\x74'] = 'abst' #'abstract' # 'abst'
	profiles['\x6E\x6D\x63\x6C'] = 'nmcl' #'named_color' # 'nmcl'
	
	# Color Space signature
	# -----------------------------
	
	color_spaces = {}
	color_spaces['\x58\x59\x5A\x20'] = 'XYZ ' # XYZData
	color_spaces['\x43\x4D\x59\x4B'] = 'CMYK' # cmykData
	color_spaces['\x11\x11\x42\x66'] = 'RGB ' # rgbData
	color_spaces['\x4C\x61\x00\xBB'] = 'Lab ' # labData
	color_spaces['\x4C\x75\x76\x20'] = 'Luv ' # luvData
	color_spaces['\x59\x43\x62\x72'] = 'YCbr' # YCbCrData
	color_spaces['\x59\x78\x79\x20'] = 'Yxy ' # YxyData
	color_spaces['\x52\x47\x42\x20'] = 'RGB ' # rgbData
	color_spaces['\x47\x52\x41\x59'] = 'GRAY' # grayData
	color_spaces['\x48\x53\x56\x20'] = 'HSV ' # hsvData
	color_spaces['\x48\x4C\x53\x20'] = 'HLS ' # hlsData
	color_spaces['\x43\x4D\x59\x4B'] = 'CMYK' # cmykData
	color_spaces['\x43\x4D\x59\x20'] = 'CMY ' # cmyData
	color_spaces['\x32\x43\x4C\x52'] = '2CLR' # 2colorData
	color_spaces['\x33\x43\x4C\x52'] = '3CLR' # 3colorData (if not listed above)
	color_spaces['\x34\x43\x4C\x52'] = '4CLR' # 4colorData (if not listed above)
	color_spaces['\x35\x43\x4C\x52'] = '5CLR' # 5colorData
	color_spaces['\x36\x43\x4C\x52'] = '6CLR' # 6colorData
	color_spaces['\x37\x43\x4C\x52'] = '7CLR' # 7colorData
	color_spaces['\x38\x43\x4C\x52'] = '8CLR' # 8colorData
	color_spaces['\x39\x43\x4C\x52'] = '9CLR' # 9colorData
	color_spaces['\x41\x43\x4C\x52'] = 'ACLR' # 10colorData
	color_spaces['\x42\x43\x4C\x52'] = 'BCLR' # 11colorData
	color_spaces['\x43\x43\x4C\x52'] = 'CCLR' # 12colorData
	color_spaces['\x44\x43\x4C\x52'] = 'DCLR' # 13colorData
	color_spaces['\x45\x43\x4C\x52'] = 'ECLR' # 14colorData
	color_spaces['\x46\x43\x4C\x52'] = 'FCLR' # 15colorData
	
	# Profile connection space (PCS)
	# -----------------------------
	
	connection_spaces = {}
	connection_spaces['\x58\x59\x5A\x20'] = 'XYZ' # XYZData
	connection_spaces['\x4C\x61\x62\x20'] = 'Lab' # labData
	
	# Primary platform signatures (for CMM)
	# -----------------------------
	
	primary_platform_signatures = {}
	primary_platform_signatures['\x41\x50\x50\x4C'] = 'APPL' # Apple Computer, Inc.
	primary_platform_signatures['\x4D\x53\x46\x54'] = 'MSFT' # Microsoft Corporation
	primary_platform_signatures['\x53\x47\x49\x20'] = 'SGI' # Silicon Graphics, Inc.
	primary_platform_signatures['\x53\x55\x4E\x57'] = 'SUNW' # Sun Microsystems, Inc.
	primary_platform_signatures['\x54\x47\x4E\x54'] = 'TGNT' # Taligent, Inc.
	
	# Measurement type
	# -----------------------------
	
	observers = {}
	observers['\x00\x00\x00\x00'] = 'unknown'
	observers['\x00\x00\x00\x01'] = 'CIE 1931 standard colorimetric observer'
	observers['\x00\x00\x00\x02'] = 'CIE 1964 standard colorimetric observer'
	
	geometries = {}
	geometries['\x00\x00\x00\x00'] = 'unknown'
	geometries['\x00\x00\x00\x01'] = '0/45 or 45/0'
	geometries['\x00\x00\x00\x02'] = '0/d or d/0'
	
	flares = {}
	flares['\x00\x00\x00\x00'] = '0 (0%)'
	flares['\x00\x00\x00\x01'] = '1,0 (or 100%)'
	
	illuminants = {}
	illuminants['\x00\x00\x00\x00'] = 'unknown'
	illuminants['\x00\x00\x00\x01'] = 'D50'
	illuminants['\x00\x00\x00\x02'] = 'D65'
	illuminants['\x00\x00\x00\x03'] = 'D93'
	illuminants['\x00\x00\x00\x04'] = 'F2'
	illuminants['\x00\x00\x00\x05'] = 'D55'
	illuminants['\x00\x00\x00\x06'] = 'A'
	illuminants['\x00\x00\x00\x07'] = 'Equi-Power (E)'
	illuminants['\x00\x00\x00\x08'] = 'F8'
	
	
	####################################################################
	#
	# __init__
	#
	####################################################################
	
	def __init__(self):
		return
	
	####################################################################
	#
	# ICC Header Information / Description
	#
	####################################################################
	
	def size(self):
		self.data.seek(0,0)
		return self.uInt32Number(self.data.read(4))
	
	def cmm_type(self):
		self.data.seek(4,0)
		return self.data.read(4).encode()
	
	def version(self):
		self.data.seek(8,0)
		return '0x' + self.data.read(4).encode('hex')[1:]
	
	def device_class(self):
		self.data.seek(12,0)
		hexdata = self.data.read(4)		
				
		if self.profiles.has_key(hexdata):
			return self.profiles[hexdata]
		else:
			return None
	
	def color_space(self):
		self.data.seek(16,0)
		hexdata = self.data.read(4)		
				
		if self.color_spaces.has_key(hexdata):
			return self.color_spaces[hexdata]
		else:
			return None
		
	def connection_space(self):
		self.data.seek(20,0)
		hexdata = self.data.read(4)		
				
		if self.connection_spaces.has_key(hexdata):
			return self.connection_spaces[hexdata]
		else:
			return None
	
	def creation_datetime(self):
		self.data.seek(24,0)
		return self.dateTimeNumber(self.data.read(12))
	
	def file_signature(self):
		"""'acsp' (61637379h)"""
		self.data.seek(36,0)
		return self.data.read(4)
	
	def primary_platform(self):
		self.data.seek(40,0)
		hexdata = self.data.read(4)		
				
		if self.primary_platform_signatures.has_key(hexdata):
			return self.primary_platform_signatures[hexdata]
		else:
			return False
	
	def flags(self):
		"""
		first bit for embedded profile 
		(0 if not embedded, 1 if embedded in file)
		
		second bit, profile cannot be used independently from 
		the embedded color data (1=True, 0=False)
		
		The least-significant 16 bits are reserved for the ICC
		"""
		self.data.seek(44,0)
		return struct.unpack('>bbbb',self.data.read(4))

	def device_manufacturer(self):
		self.data.seek(48,0)
		manufacturer = self.data.read(4).encode().replace('\00','')
		
		if manufacturer:
			return manufacturer
		else:
			return ''

	def device_model(self):
		self.data.seek(52,0)
		return self.data.read(4).encode('hex')

	def device_attributes(self):
		""" 
		first bit, Reflective (0) or Transparency (1)
		second bit, Glossy (0) or Matte (1)
		third bit, Media polarity - Positive (0) or Negative (1)
		fourth bit, Colour media (0), Black & white media (1)
		"""
		
		self.data.seek(56,0)
		return struct.unpack('>bbbb',self.data.read(4))
	
	def rendering_intent(self):
		"""
		0 = perceptual
		1 = relative colorimetric
		2 = saturation
		3 = absolute colorimetric
		"""
		self.data.seek(64,0)
		return struct.unpack('>i',self.data.read(4))[0]
	
	def illuminant(self):		
		"""X,Y,Z = [0,9642 1,0 0,8249] is for D50"""
		
		self.data.seek(68,0)
		return self.XYZNumber(self.data.read(12))
	
	def creator_signature(self):
		self.data.seek(80,0)
		return self.data.read(4).encode()
	
	def profile_id(self):
		self.data.seek(84,0)
		return self.data.read(16).encode('hex')
	
	def reserved_bytes(self):
		self.data.seek(100,0)
		return self.data.read(28).encode('hex')
	
	####################################################################
	#
	# Tag table, tagged element data
	#
	####################################################################
		
	def tag_count(self):
		self.data.seek(128,0)
		return self.uInt32Number(self.data.read(4))
	
	def tag_get_by_key(self, key):
		"""Tag key number is the position key in the tag_array"""
		
		# 12 bytes for each tag		
		# tag table starts at 132 bytes
		tag_position = 132 + (12 * key)
		
		self.data.seek(tag_position,0)
		
		return (self.data.read(4).encode(), 
				self.uInt32Number(self.data.read(4)), 
				self.uInt32Number(self.data.read(4)))
	
	def tag_array(self):			
		"""Returns a list of tuples with signature,offset,size values"""
		tag_array = []
				
		for i in range(self.tag_count()):
			tag_array.append(self.tag_get_by_key(i))
				
		return tag_array

	def tag_data(self, position=None):
		"""Retrievs tag data based on the order position in tag table"""
		try:
			sig,offset,size = self.tag_get_by_key(position)
			self.data.seek(offset)
			return self.data.read(size)
		except:
			return None


	####################################################################
	#
	# Functions, Tag type definitions
	#
	####################################################################
	
	def chromaticityType(self, data):
		pass
	
	def colorantOrderType(self, data):
		pass
		
	def colorantTableType(self, data):
		pass
	
	def curvType(self, curv_data):
		curv_data = curv_data[4:]
		rows = self.uInt32Number(curv_data[4:8])
		
		data = []
		
		if rows is 1:
			start = 8
			end = 10
			data.append(self.u8Fixed8Number(curv_data[start:end]))
		else:
			for i in range(rows):
				start = 8 + i*2
				end = 10 + i*2
				data.append(self.uInt16Number(curv_data[start:end]))
		
		return data
	
	def dataType(self, data):
		return data
	
	def dateTimeType(self, data):
		return self.dateTimeNumber(data[8:])
	
	def lut16Type(self, data):
		pass
	
	def lut8Type(self, data):
		pass
	
	def lutAtoBType(self, data):
		signature = data[:4]
		
		input_channels 	= self.uInt8Number(data[8])
		output_channels = self.uInt8Number(data[9])
		
		# If any of the offsets are zero, that is an indication that 
		# processing element is not present and the operation is not performed

		offset_B 		= self.uInt32Number(data[12:16])
		offset_matrix 	= self.uInt32Number(data[16:20])
		offset_M 		= self.uInt32Number(data[20:24])
		offset_clut 	= self.uInt32Number(data[24:28])
		offset_A 		= self.uInt32Number(data[28:32])
		
		print offset_B, offset_matrix, offset_M, offset_clut, offset_A
		
		array = []		
		[array.append(data[offset_matrix+i:offset_matrix+i+4]) for i in range(0,48,4)]
		
		matrix = []
		[matrix.append(self.s15Fixed16Number(i)) for i in array]
		
		print matrix
		
		#rows = self.uInt32Number(data[offset_M+8:offset_M+12])
		#print rows
		
		return input_channels, output_channels, matrix
	
	def lutBtoAType(self, data):
		pass
	
	def measurementType(self, data):
		"""Returns a list (observer, XYZNumber, measurement, flare, illuminant)"""
		
		return (self.observers[data[4:8]],
				self.XYZNumber(data[8:24]),
				self.geometries[data[24:28]],
				self.flares[data[28:32]],
				self.illuminants[data[32:26]]
				)

	def multiLocalizedUnicodeType(self, data):
		"""
		Returns a list 
		(n, name record size, language code, country code, lenght, offset, unicode text)
		"""
		# this is taken from icc v2
		# TODO: Make it true icc v4
		
		if(data[:4] == 'mluc'):
			n = self.uInt32Number(data[8:12])	
			name_record_size = self.uInt32Number(data[12:16])
			lang_code = data[16:18]
			country_code = data[18:20]
			lenght = self.uInt32Number(data[20:24])
			offset = self.uInt32Number(data[24:28])
			text = data[offset:(offset+lenght)]
			#print n, name_record_size, lang_code, country_code, lenght, offset, text
			return n, name_record_size, lang_code, country_code, lenght, offset, text
		else:
			return self.textDescriptionType(data)
		
	
	def textDescriptionType(self,data):
		# this is taken from icc v2
		# depricated in v4 multiLocalizedUnicodeType is used
		n = self.uInt32Number(data[8:12])	
		return data[12:(12+n-1)]
	
	def namedColor2Type(self, data):
		pass
	
	def parametricCurveType(self, data):
		pass
	
	def profileSequenceDescType(self, data):
		pass
	
	def responseCurveSet16Type(self, data):
		pass
	
	def s15Fixed16ArrayType(self, sf32_data):
		sf32_numbers = sf32_data[8:]
		X,Y,Z, X1,Y1,Z1, X2,Y2,Z2 = struct.unpack('>iiiiiiiii',sf32_numbers)
		X = (X / 65536.0)
		Y = (Y / 65536.0)
		Z = (Z / 65536.0)
		
		X1 = (X1 / 65536.0)
		Y1 = (Y1 / 65536.0)
		Z1 = (Z1 / 65536.0)
		
		X2 = (X2 / 65536.0)
		Y2 = (Y2 / 65536.0)
		Z2 = (Z2 / 65536.0)
		
		return X,Y,Z, X1,Y1,Z1, X2,Y2,Z2
	
	def signatureType(self, data):
		return data[8:12]
		
	def textType(self, text):
		return text[8:]
	
	def u16Fixed16ArrayType(self, data):
		data = data[8:]
		bytes = 4
		numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
		return [self.u16Fixed16Number(i) for i in numbers]	
	
	def uInt8ArrayType(self, data):	
		data = data[8:]
		bytes = 1
		numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
		return [self.uInt8Number(i) for i in numbers]
	
	def uInt16ArrayType(self, data):	
		data = data[8:]
		bytes = 2
		numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
		return [self.uInt16Number(i) for i in numbers]
	
	def uInt32ArrayType(self, data):	
		data = data[8:]
		bytes = 4
		numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
		return [self.uInt32Number(i) for i in numbers]
	
	def uInt64ArrayType(self, data):	
		data = data[8:]
		bytes = 8
		numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
		return [self.uInt64Number(i) for i in numbers]
	
	def viewingConditionsType(self, data):
		"""
		Returns a list
		0) XYZNumber - CIE 'absolute' XYZ values for illuminant (in which Y is in cd/m2)
		1) XYZNumber - CIE 'absolute' XYZ values for surround (in which Y is in cd/m2)
		2) illuminant type
		"""
		return (self.XYZNumber(data[8:20]),
				self.XYZNumber(data[20:32]),
				self.illuminants(data[32:36])
				)
				
	def XYZType(self, data):	
		data = data[8:]
		if len(data) > 12:
			bytes = 12
			numbers = [data[i:i+bytes] for i in range(0, len(data), bytes)]
			return [self.XYZNumber(i) for i in numbers]
		else:
			return self.XYZNumber(data)

		
class open_file(icc):
	
	def __init__(self,icc_file):
		self.data = open(icc_file,'r+b')
